home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 2 / Amiga Tools 2.iso / tools / vim / src / fileio.c < prev    next >
C/C++ Source or Header  |  1995-03-09  |  32KB  |  1,264 lines

  1. /* vi:ts=4:sw=4
  2.  *
  3.  * VIM - Vi IMproved        by Bram Moolenaar
  4.  *
  5.  * Read the file "credits.txt" for a list of people who contributed.
  6.  * Read the file "uganda.txt" for copying and usage conditions.
  7.  */
  8.  
  9. /*
  10.  * fileio.c: read from and write to a file
  11.  */
  12.  
  13. /*
  14.  * special feature of this version: NUL characters in the file are
  15.  * replaced by newline characters in memory. This allows us to edit
  16.  * binary files!
  17.  */
  18.  
  19. #ifdef MSDOS
  20. # include <io.h>
  21. #endif
  22.  
  23. #include "vim.h"
  24. #include "globals.h"
  25. #include "proto.h"
  26. #include "param.h"
  27. #include "fcntl.h"
  28.  
  29. #ifdef LATTICE
  30. # include <proto/dos.h>        /* for Lock() and UnLock() */
  31. #endif
  32.  
  33. #define BUFSIZE        8192            /* size of normal write buffer */
  34. #define SBUFSIZE    256                /* size of emergency write buffer */
  35.  
  36. static int  write_buf __ARGS((int, char_u *, int));
  37. static void do_mlines __ARGS((void));
  38.  
  39.     void
  40. filemess(name, s)
  41.     char_u        *name;
  42.     char_u        *s;
  43. {
  44.         /* careful: home_replace calls vimgetenv(), which also uses IObuff! */
  45.     home_replace(name, IObuff + 1, IOSIZE - 1);
  46.     IObuff[0] = '"';
  47.     STRCAT(IObuff, "\" ");
  48.     STRCAT(IObuff, s);
  49.     /*
  50.      * don't use msg(), because it sometimes outputs a newline
  51.      */
  52.     msg_start();
  53.     msg_outstr(IObuff);
  54.     msg_ceol();
  55.     flushbuf();
  56. }
  57.  
  58. /*
  59.  * Read lines from file 'fname' into the buffer after line 'from'.
  60.  *
  61.  * 1. We allocate blocks with lalloc, as big as possible.
  62.  * 2. Each block is filled with characters from the file with a single read().
  63.  * 3. The lines are inserted in the buffer with ml_append().
  64.  *
  65.  * (caller must check that fname != NULL)
  66.  *
  67.  * skip_lnum is the number of lines that must be skipped
  68.  * nlines is the number of lines that are appended
  69.  * When not recovering skip_lnum is 0 and nlines MAXLNUM.
  70.  *
  71.  * return FAIL for failure, OK otherwise
  72.  */
  73.     int
  74. readfile(fname, sfname, from, newfile, skip_lnum, nlines)
  75.     char_u           *fname;
  76.     char_u           *sfname;
  77.     linenr_t        from;
  78.     int                newfile;
  79.     linenr_t        skip_lnum;
  80.     linenr_t        nlines;
  81. {
  82. #ifdef UNIX
  83.     int                 fd = -1;
  84. #else
  85.     int                 fd;
  86. #endif
  87.     register char_u     c;
  88.     register linenr_t    lnum = from;
  89.     register char_u     *ptr = NULL;            /* pointer into read buffer */
  90.     register char_u        *buffer = NULL;            /* read buffer */
  91.     char_u                *new_buffer = NULL;        /* init to shut up gcc */
  92.     char_u                *line_start = NULL;        /* init to shut up gcc */
  93.     colnr_t                len;
  94.     register long        size;
  95.     register char_u        *p;
  96.     long                filesize = 0;
  97.     int                    split = 0;                /* number of split lines */
  98. #define UNKNOWN        0x0fffffff                    /* file size is unknown */
  99.     linenr_t            linecnt = curbuf->b_ml.ml_line_count;
  100.     int                    incomplete = FALSE;     /* was the last line incomplete? */
  101.     int                 error = FALSE;            /* errors encountered */
  102.     long                linerest = 0;            /* remaining characters in line */
  103.     int                    firstpart = TRUE;        /* reading first part */
  104. #ifdef UNIX
  105.     int                    perm;
  106. #endif
  107.     int                    textmode = curbuf->b_p_tx;        /* accept CR-LF for line break */
  108.     struct stat            st;
  109.     int                    readonly;
  110.  
  111.     /*
  112.      * If there is no file name yet, use the one for the read file.
  113.      * b_notedited is set to reflect this.
  114.      */
  115.     if (curbuf->b_filename == NULL)
  116.     {
  117.         if (setfname(fname, sfname, FALSE) == OK)
  118.             curbuf->b_notedited = TRUE;
  119.     }
  120.  
  121.     if (sfname == NULL)
  122.         sfname = fname;
  123.     /*
  124.      * Use the short filename whenever possible.
  125.      * Avoids problems with networks and when directory names are changed.
  126.      */
  127.     if (!did_cd)
  128.         fname = sfname;
  129.  
  130.     if (bufempty())        /* special case: buffer has no lines */
  131.         linecnt = 0;
  132.  
  133. #ifdef UNIX
  134.     /*
  135.      * On Unix it is possible to read a directory, so we have to
  136.      * check for it before the open().
  137.      */
  138.     perm = getperm(fname);
  139. # ifdef _POSIX_SOURCE
  140.     if (perm >= 0 && !S_ISREG(perm))                /* not a regular file */
  141. # else
  142.     if (perm >= 0 && (perm & S_IFMT) != S_IFREG)    /* not a regular file */
  143. # endif
  144.     {
  145. # ifdef _POSIX_SOURCE
  146.         if (S_ISDIR(perm))
  147. # else
  148.         if ((perm & S_IFMT) == S_IFDIR)
  149. # endif
  150.             filemess(fname, (char_u *)"is a directory");
  151.         else
  152.             filemess(fname, (char_u *)"is not a file");
  153.         return FAIL;
  154.     }
  155. #endif
  156.  
  157.     if (newfile && !readonlymode)            /* default: set file not readonly */
  158.         curbuf->b_p_ro = FALSE;
  159.  
  160.     if (newfile && stat((char *)fname, &st) != -1)    /* remember time of file */
  161.         curbuf->b_mtime = st.st_mtime;
  162.     else
  163.         curbuf->b_mtime = 0;
  164.  
  165. /*
  166.  * for UNIX: check readonly with perm and access()
  167.  * for MSDOS and Amiga: check readonly by trying to open the file for writing
  168.  */
  169.     readonly = FALSE;
  170. #ifdef UNIX
  171.     if (!(perm & 0222) || access((char *)fname, 2))
  172.         readonly = TRUE;
  173.     fd = open((char *)fname, O_RDONLY);
  174. #else
  175.     if (!newfile || readonlymode || (fd = open((char *)fname, O_RDWR)) < 0)
  176.     {
  177.         readonly = TRUE;
  178.         fd = open((char *)fname, O_RDONLY);            /* try to open ro */
  179.     }
  180. #endif
  181.  
  182.     if (fd < 0)                     /* cannot open at all */
  183.     {
  184. #ifdef MSDOS
  185.     /*
  186.      * The screen may be messed up by the "insert disk
  187.      * in drive b: and hit return" message
  188.      */
  189.         screenclear();
  190. #endif
  191.  
  192. #ifndef UNIX
  193.     /*
  194.      * On MSDOS and Amiga we can't open a directory, check here.
  195.      */
  196.         if (isdir(fname) == TRUE)
  197.             filemess(fname, (char_u *)"is a directory");
  198.         else
  199. #endif
  200.             if (newfile)
  201. #ifdef UNIX
  202.                 if (perm < 0)
  203. #endif
  204.                     filemess(fname, (char_u *)"[New File]");
  205. #ifdef UNIX
  206.                 else
  207.                     filemess(fname, (char_u *)"[Permission Denied]");
  208. #endif
  209.  
  210.         return FAIL;
  211.     }
  212.     if (newfile && readonly)                    /* set file readonly */
  213.         curbuf->b_p_ro = TRUE;
  214.  
  215.     if (newfile)
  216.         curbuf->b_p_eol = TRUE;
  217.  
  218.     ++no_wait_return;                            /* don't wait for return yet */
  219.     if (!recoverymode)
  220.         filemess(fname, (char_u *)"");            /* show that we are busy */
  221.  
  222.     while (!error && !got_int)
  223.     {
  224.         /*
  225.          * We allocate as much space for the file as we can get, plus
  226.          * space for the old line plus room for one terminating NUL.
  227.          * The amount is limited by the fact that read() only can read
  228.          * upto max_unsigned characters (and other things).
  229.          */
  230. #if defined(AMIGA) || defined(MSDOS)
  231.         if (sizeof(int) <= 2 && linerest >= 0x7ff0)
  232.         {
  233.             ++split;
  234.             *ptr = NL;                /* split line by inserting a NL */
  235.             size = 1;
  236.         }
  237.         else
  238. #endif
  239.         {
  240. #if !(defined(AMIGA) || defined(MSDOS))
  241.             if (sizeof(int) > 2)
  242.                 size = 0x10000L;                /* read 64K at a time */
  243.             else
  244. #endif
  245.                 size = 0x7ff0L - linerest;        /* limit buffer to 32K */
  246.  
  247.             for ( ; size >= 10; size >>= 1)
  248.             {
  249.                 if ((new_buffer = lalloc((long_u)(size + linerest + 1), FALSE)) != NULL)
  250.                     break;
  251.             }
  252.             if (new_buffer == NULL)
  253.             {
  254.                 emsg(e_outofmem);
  255.                 error = TRUE;
  256.                 break;
  257.             }
  258.             if (linerest)        /* copy characters from the previous buffer */
  259.                 memmove((char *)new_buffer, (char *)ptr - linerest, linerest);
  260.             free(buffer);
  261.             buffer = new_buffer;
  262.             ptr = buffer + linerest;
  263.             line_start = buffer;
  264.             
  265.             if ((size = read(fd, (char *)ptr, (size_t)size)) <= 0)
  266.             {
  267.                 if (size < 0)                /* read error */
  268.                     error = TRUE;
  269.                 break;
  270.             }
  271.             filesize += size;                /* count the number of characters */
  272.  
  273.             /*
  274.              * when reading the first part of a file: guess EOL type
  275.              */
  276.             if (firstpart && p_ta)
  277.             {
  278.                 for (p = ptr; p < ptr + size; ++p)
  279.                     if (*p == NL)
  280.                     {
  281.                         if (p > ptr && p[-1] == CR)    /* found CR-NL */
  282.                             textmode = TRUE;
  283.                         else                        /* found a single NL */
  284.                             textmode = FALSE;
  285.                             /* if editing a new file: may set p_tx */
  286.                         if (newfile && curbuf->b_p_tx != textmode)
  287.                         {
  288.                             curbuf->b_p_tx = textmode;
  289.                             paramchanged((char_u *)"tx");
  290.                         }
  291.                         break;
  292.                     }
  293.             }
  294.         }
  295.  
  296.         /*
  297.          * This loop is executed once for every character read.
  298.          * Keep it fast!
  299.          */
  300.         --ptr;
  301.         while (++ptr, --size >= 0)
  302.         {
  303.             if ((c = *ptr) != NUL && c != NL)    /* catch most common case */
  304.                 continue;
  305.             if (c == NUL)
  306.                 *ptr = NL;        /* NULs are replaced by newlines! */
  307.             else
  308.             {
  309.                 if (skip_lnum == 0)
  310.                 {
  311.                     *ptr = NUL;        /* end of line */
  312.                     len = ptr - line_start + 1;
  313.                     if (textmode && ptr[-1] == CR)    /* remove CR */
  314.                     {
  315.                         ptr[-1] = NUL;
  316.                         --len;
  317.                     }
  318.                     if (ml_append(lnum, line_start, len, newfile) == FAIL)
  319.                     {
  320.                         error = TRUE;
  321.                         break;
  322.                     }
  323.                     ++lnum;
  324.                     if (--nlines == 0)
  325.                     {
  326.                         error = TRUE;        /* break loop */
  327.                         line_start = ptr;    /* nothing left to write */
  328.                         break;
  329.                     }
  330.                 }
  331.                 else
  332.                     --skip_lnum;
  333.                 line_start = ptr + 1;
  334.             }
  335.         }
  336.         linerest = ptr - line_start;
  337.         firstpart = FALSE;
  338.         breakcheck();
  339.     }
  340.  
  341.     if (error && nlines == 0)        /* not an error, max. number of lines reached */
  342.         error = FALSE;
  343.  
  344.     if (!error && !got_int && linerest != 0
  345. #ifdef MSDOS
  346.     /*
  347.      * in MSDOS textmode ignore a trailing CTRL-Z
  348.      */
  349.         && !(!curbuf->b_p_bin && *line_start == Ctrl('Z') && ptr == line_start + 1)
  350. #endif
  351.                                     )
  352.     {
  353.         /*
  354.          * If we get EOF in the middle of a line, note the fact and
  355.          * complete the line ourselves.
  356.          */
  357.         incomplete = TRUE;
  358.         if (newfile && curbuf->b_p_bin)        /* remember for when writing */
  359.             curbuf->b_p_eol = FALSE;
  360.         *ptr = NUL;
  361.         if (ml_append(lnum, line_start, (colnr_t)(ptr - line_start + 1), newfile) == FAIL)
  362.             error = TRUE;
  363.         else
  364.             ++lnum;
  365.     }
  366.     if (lnum != from && !newfile)    /* added at least one line */
  367.         CHANGED;
  368.  
  369.     close(fd);
  370.     free(buffer);
  371.  
  372.     --no_wait_return;                /* may wait for return now */
  373.     if (recoverymode)                /* in recovery mode return here */
  374.     {
  375.         if (error)
  376.             return FAIL;
  377.         return OK;
  378.     }
  379.  
  380. #ifdef MSDOS                    /* the screen may be messed up by the "insert disk
  381.                                     in drive b: and hit return" message */
  382.     screenclear();
  383. #endif
  384.  
  385.     linecnt = curbuf->b_ml.ml_line_count - linecnt;
  386.     if (!newfile)
  387.         mark_adjust(from + 1, MAXLNUM, (long)linecnt);
  388.  
  389.     if (got_int)
  390.     {
  391.         filemess(fname, e_interr);
  392.         return OK;            /* an interrupt isn't really an error */
  393.     }
  394.  
  395.         /* careful: home_replace calls vimgetenv(), which also uses IObuff! */
  396.     home_replace(fname, IObuff + 1, IOSIZE - 1);
  397.     IObuff[0] = '"';
  398.     sprintf((char *)IObuff + STRLEN(IObuff),
  399.                     "\" %s%s%s%s%s%ld line%s, %ld character%s",
  400.             curbuf->b_p_ro ? "[readonly] " : "",
  401.             incomplete ? "[Incomplete last line] " : "",
  402.             split ? "[long lines split] " : "",
  403.             error ? "[READ ERRORS] " : "",
  404. #ifdef MSDOS
  405.             textmode ? "" : "[notextmode] ",
  406. #else
  407.             textmode ? "[textmode] " : "",
  408. #endif
  409.             (long)linecnt, plural((long)linecnt),
  410.             filesize, plural(filesize));
  411.     msg(IObuff);
  412.  
  413.     if (error && newfile)    /* with errors we should not write the file */
  414.     {
  415.         curbuf->b_p_ro = TRUE;
  416.         paramchanged((char_u *)"ro");
  417.     }
  418.  
  419.     u_clearline();        /* cannot use "U" command after adding lines */
  420.  
  421.     if (newfile)        /* edit a new file: read mode from lines */
  422.         do_mlines();
  423.     if (from < curbuf->b_ml.ml_line_count)
  424.     {
  425.         curwin->w_cursor.lnum = from + 1;    /* put cursor at first new line */
  426.         curwin->w_cursor.col = 0;
  427.     }
  428.  
  429.     return OK;
  430. }
  431.  
  432. /*
  433.  * writeit - write to file 'fname' lines 'start' through 'end'
  434.  *
  435.  * We do our own buffering here because fwrite() is so slow.
  436.  *
  437.  * If forceit is true, we don't care for errors when attempting backups (jw).
  438.  * In case of an error everything possible is done to restore the original file.
  439.  * But when forceit is TRUE, we risk loosing it.
  440.  * When reset_changed is TRUE and start == 1 and end ==
  441.  * curbuf->b_ml.ml_line_count, reset curbuf->b_changed.
  442.  *
  443.  * return FAIL for failure, OK otherwise
  444.  */
  445.     int
  446. buf_write(buf, fname, sfname, start, end, append, forceit, reset_changed)
  447.     BUF                *buf;
  448.     char_u            *fname;
  449.     char_u            *sfname;
  450.     linenr_t        start, end;
  451.     int                append;
  452.     int                forceit;
  453.     int                reset_changed;
  454. {
  455.     int                 fd;
  456.     char_u               *backup = NULL;
  457.     char_u               *ffname;
  458.     register char_u       *s;
  459.     register char_u       *ptr;
  460.     register char_u        c;
  461.     register int        len;
  462.     register linenr_t    lnum;
  463.     long                nchars;
  464.     char_u                *errmsg = NULL;
  465.     char_u                *buffer;
  466.     char_u                smallbuf[SBUFSIZE];
  467.     int                    bufsize;
  468.     long                 perm = -1;            /* file permissions */
  469.     int                    retval = OK;
  470.     int                    newfile = FALSE;    /* TRUE if file does not exist yet */
  471. #ifdef UNIX
  472.     struct stat            old;
  473.     int                    made_writable = FALSE;    /* 'w' bit has been set */
  474. #endif
  475. #ifdef AMIGA
  476.     BPTR                flock;
  477. #endif
  478.                                             /* writing everything */
  479.     int                    whole = (start == 1 && end == buf->b_ml.ml_line_count);
  480.  
  481.     if (fname == NULL || *fname == NUL)        /* safety check */
  482.         return FAIL;
  483.  
  484.     /*
  485.      * If there is no file name yet, use the one for the written file.
  486.      * b_notedited is set to reflect this (in case the write fails).
  487.      */
  488.     if (reset_changed && whole && buf == curbuf && curbuf->b_filename == NULL)
  489.     {
  490.         if (setfname(fname, sfname, FALSE) == OK)
  491.             curbuf->b_notedited = TRUE;
  492.     }
  493.  
  494.     if (sfname == NULL)
  495.         sfname = fname;
  496.     /*
  497.      * Use the short filename whenever possible.
  498.      * Avoids problems with networks and when directory names are changed.
  499.      */
  500.     ffname = fname;                            /* remember full fname */
  501.     if (!did_cd)
  502.         fname = sfname;
  503.  
  504.     /*
  505.      * Disallow writing from .exrc and .vimrc in current directory for
  506.      * security reasons.
  507.      */
  508.     if (secure)
  509.     {
  510.         secure = 2;
  511.         emsg(e_curdir);
  512.         return FAIL;
  513.     }
  514.  
  515.     if (exiting)
  516.         settmode(0);                /* when exiting allow typahead now */
  517.  
  518.     ++no_wait_return;                /* don't wait for return yet */
  519.     filemess(fname, (char_u *)"");    /* show that we are busy */
  520.  
  521.     buffer = alloc(BUFSIZE);
  522.     if (buffer == NULL)                /* can't allocate big buffer, use small one */
  523.     {
  524.         buffer = smallbuf;
  525.         bufsize = SBUFSIZE;
  526.     }
  527.     else
  528.         bufsize = BUFSIZE;
  529.  
  530. #if defined(UNIX) && !defined(ARCHIE)
  531.         /* get information about original file (if there is one) */
  532.     old.st_dev = old.st_ino = 0;
  533.     if (stat((char *)fname, &old))
  534.         newfile = TRUE;
  535.     else
  536.     {
  537. #ifdef _POSIX_SOURCE
  538.         if (!S_ISREG(old.st_mode))              /* not a file */
  539. #else
  540.         if ((old.st_mode & S_IFMT) != S_IFREG)    /* not a file */
  541. #endif
  542.         {
  543. #ifdef _POSIX_SOURCE
  544.             if (S_ISDIR(old.st_mode))
  545. #else
  546.             if ((old.st_mode & S_IFMT) == S_IFDIR)
  547. #endif
  548.                 errmsg = (char_u *)"is a directory";
  549.             else
  550.                 errmsg = (char_u *)"is not a file";
  551.             goto fail;
  552.         }
  553.         perm = old.st_mode;
  554.     }
  555. /*
  556.  * If we are not appending, the file exists, and the 'writebackup', 'backup'
  557.  * or 'patchmode' option is set, try to make a backup copy of the file.
  558.  */
  559.     if (!append && perm >= 0 && (p_wb || p_bk || (p_pm != NULL && *p_pm != NUL)) &&
  560.                     (fd = open((char *)fname, O_RDONLY)) >= 0)
  561.     {
  562.         int                bfd, buflen;
  563.         char_u            copybuf[BUFSIZE + 1], *wp;
  564.         int                some_error = FALSE;
  565.         struct stat        new;
  566.  
  567.         new.st_dev = new.st_ino = 0;
  568.  
  569.         /*
  570.          * Unix semantics has it, that we may have a writable file, 
  571.          * that cannot be recreated with a simple open(..., O_CREAT, ) e.g:
  572.          *  - the directory is not writable, 
  573.          *  - the file may be a symbolic link, 
  574.          *  - the file may belong to another user/group, etc.
  575.          *
  576.          * For these reasons, the existing writable file must be truncated and
  577.          * reused. Creation of a backup COPY will be attempted.
  578.          */
  579.         if (*p_bdir != '>')            /* try to put .bak in current dir */
  580.         {
  581.             if ((backup = modname(fname, ".bak")) == NULL)
  582.             {
  583.                 some_error = TRUE;            /* out of memory */
  584.                 goto nobackup;
  585.             }            
  586.             if (!stat((char *)backup, &new) &&
  587.                         new.st_dev == old.st_dev && new.st_ino == old.st_ino)
  588.             {
  589.                 /*
  590.                  * may happen when modname gave the same file back.
  591.                  * E.g. silly link, or filename-length reached.
  592.                  * If we don't check here, we either ruin the file when
  593.                  * copying or erase it after writing. jw.
  594.                  */
  595.                 free(backup);
  596.                 backup = NULL;    /* there is no backup file to delete */
  597.                 if (*p_bdir == NUL)
  598.                 {
  599.                     errmsg = (char_u *)"Invalid backup file (use ! to override)";
  600.                     goto nobackup;
  601.                 }
  602.             }
  603.             else
  604.                 remove((char *)backup);        /* remove old backup, if present */
  605.         }
  606.         if (backup == NULL || (bfd = open((char *)backup, O_WRONLY | O_CREAT, 0666)) < 0)
  607.         {
  608.             /* 
  609.              * 'backupdir' starts with '>' or  no write/create permission
  610.              * in current dirr: try again in p_bdir directory. 
  611.              */
  612.             free(backup);
  613.             wp = gettail(fname);
  614.             sprintf((char *)copybuf, "%s/%s", *p_bdir == '>' ? p_bdir + 1 : p_bdir, wp);
  615.             if ((backup = buf_modname(buf, copybuf, (char_u *)".bak")) == NULL)
  616.             {
  617.                 some_error = TRUE;            /* out of memory */
  618.                 goto nobackup;
  619.             }
  620.             if (!stat((char *)backup, &new) &&
  621.                         new.st_dev == old.st_dev && new.st_ino == old.st_ino)
  622.             {
  623.                 errmsg = (char_u *)"Invalid backup file (use ! to override)";
  624.                 free(backup);
  625.                 backup = NULL;    /* there is no backup file to delete */
  626.                 goto nobackup;
  627.             }
  628.             remove((char *)backup);
  629.             if ((bfd = open((char *)backup, O_WRONLY | O_CREAT, 0666)) < 0)
  630.             {
  631.                 free(backup);
  632.                 backup = NULL;    /* there is no backup file to delete */
  633.                 errmsg = (char_u *)"Can't make backup file (use ! to override)";
  634.                 goto nobackup;
  635.             }
  636.         }
  637.         /* set file protection same as original file, but strip s-bit */
  638.         (void)setperm(backup, perm & 0777);
  639.  
  640.         /* copy the file. */
  641.         while ((buflen = read(fd, (char *)copybuf, BUFSIZE)) > 0)
  642.         {
  643.             if (write_buf(bfd, copybuf, buflen) == FAIL)
  644.             {
  645.                 errmsg = (char_u *)"Can't write to backup file (use ! to override)";
  646.                 goto writeerr;
  647.             }
  648.         }
  649. writeerr:
  650.         close(bfd);
  651.         if (buflen < 0)
  652.             errmsg = (char_u *)"Can't read file for backup (use ! to override)";
  653. nobackup:
  654.         close(fd);
  655.     /* ignore errors when forceit is TRUE */
  656.         if ((some_error || errmsg) && !forceit)
  657.         {
  658.             retval = FAIL;
  659.             goto fail;
  660.         }
  661.         errmsg = NULL;
  662.     }
  663.         /* if forceit and the file was read-only: make it writable */
  664.     if (forceit && (old.st_uid == getuid()) && perm >= 0 && !(perm & 0200))
  665.      {
  666.         perm |= 0200;    
  667.         (void)setperm(fname, perm);
  668.         made_writable = TRUE;
  669.             /* if we are writing to the current file, readonly makes no sense */
  670.         if (fname == buf->b_filename || fname == buf->b_sfilename)
  671.             buf->b_p_ro = FALSE;
  672.      }
  673. #else /* end of UNIX, start of the rest */
  674.  
  675. /*
  676.  * If we are not appending, the file exists, and the 'writebackup' or
  677.  * 'backup' option is set, make a backup.
  678.  * Do not make any backup, if "writebackup" and "backup" are 
  679.  * both switched off. This helps when editing large files on
  680.  * almost-full disks. (jw)
  681.  */
  682.     perm = getperm(fname);
  683.     if (perm < 0)
  684.         newfile = TRUE;
  685.     else if (isdir(fname) == TRUE)
  686.     {
  687.         errmsg = (char_u *)"is a directory";
  688.         goto fail;
  689.     }
  690.     if (!append && perm >= 0 && (p_wb || p_bk || (p_pm != NULL && *p_pm != NUL)))
  691.     {
  692.         /*
  693.          * Form the backup file name - change path/fo.o.h to path/fo.o.h.bak
  694.          */
  695.         backup = buf_modname(buf, fname, (char_u *)".bak");
  696.         if (backup == NULL)
  697.         {
  698.             if (!forceit)
  699.                 goto fail;
  700.         }
  701.         else
  702.         {
  703.             /*
  704.              * Delete any existing backup and move the current version to the backup.
  705.              * For safety, we don't remove the backup until the write has finished
  706.              * successfully. And if the 'backup' option is set, leave it around.
  707.              */
  708. #ifdef AMIGA
  709.             /*
  710.              * With MSDOS-compatible filesystems (crossdos, messydos) it is
  711.              * possible that the name of the backup file is the same as the
  712.              * original file. To avoid the chance of accidently deleting the
  713.              * original file (horror!) we lock it during the remove.
  714.              * This should not happen with ":w", because startscript() should
  715.              * detect this problem and set buf->b_shortname, causing modname to
  716.              * return a correct ".bak" filename. This problem does exist with
  717.              * ":w filename", but then the original file will be somewhere else
  718.              * so the backup isn't really important. If autoscripting is off
  719.              * the rename may fail.
  720.              */
  721.             flock = Lock((UBYTE *)fname, (long)ACCESS_READ);
  722. #endif
  723.             remove((char *)backup);
  724. #ifdef AMIGA
  725.             if (flock)
  726.                 UnLock(flock);
  727. #endif
  728.             len = rename((char *)fname, (char *)backup);
  729.             if (len != 0)
  730.             {
  731.                 if (forceit)
  732.                 {
  733.                     free(backup);    /* don't do the rename below */
  734.                     backup = NULL;
  735.                 }
  736.                 else
  737.                 {
  738.                     errmsg = (char_u *)"Can't make backup file (use ! to override)";
  739.                     goto fail;
  740.                 }
  741.             }
  742.         }
  743.     }
  744. #endif /* UNIX */
  745.  
  746.     /*
  747.      * If the original file is being overwritten, there is a small chance that
  748.      * we crash in the middle of writing. Therefore the file is preserved now.
  749.      * This makes all block numbers positive so that recovery does not need
  750.      * the original file.
  751.      * Don't do this if there is a backup file and we are exiting.
  752.      */
  753.     if (reset_changed && !newfile && !otherfile(ffname) && !(exiting && backup != NULL))
  754.         ml_preserve(buf, FALSE);
  755.  
  756.     /* 
  757.      * We may try to open the file twice: If we can't write to the
  758.      * file and forceit is TRUE we delete the existing file and try to create
  759.      * a new one. If this still fails we may have lost the original file!
  760.      * (this may happen when the user reached his quotum for number of files).
  761.      * Appending will fail if the file does not exist and forceit is FALSE.
  762.      */
  763.     while ((fd = open((char *)fname, O_WRONLY | (append ?
  764.                     (forceit ? (O_APPEND | O_CREAT) : O_APPEND) :
  765.                     (O_CREAT | O_TRUNC)), 0666)) < 0)
  766.      {
  767.         /*
  768.          * A forced write will try to create a new file if the old one is
  769.          * still readonly. This may also happen when the directory is
  770.          * read-only. In that case the remove() will fail.
  771.          */
  772.         if (!errmsg)
  773.         {
  774.             errmsg = (char_u *)"Can't open file for writing";
  775.             if (forceit)
  776.             {
  777. #ifdef UNIX
  778.                 /* we write to the file, thus it should be marked
  779.                                                     writable after all */
  780.                 perm |= 0200;        
  781.                 made_writable = TRUE;
  782.                 if (old.st_uid != getuid() || old.st_gid != getgid())
  783.                     perm &= 0777;
  784. #endif /* UNIX */
  785.                 if (!append)        /* don't remove when appending */
  786.                     remove((char *)fname);
  787.                 continue;
  788.             }
  789.         }
  790. /*
  791.  * If we failed to open the file, we don't need a backup. Throw it away.
  792.  * If we moved or removed the original file try to put the backup in its place.
  793.  */
  794.          if (backup != NULL)
  795.         {
  796. #ifdef UNIX
  797.             struct stat st;
  798.  
  799.             /*
  800.              * There is a small chance that we removed the original, try
  801.              * to move the copy in its place.
  802.              * This won't work if the backup is in another file system!
  803.              * In that case we leave the copy around.
  804.              */
  805.             if (stat((char *)fname, &st) < 0)    /* file does not exist */
  806.                 rename((char *)backup, (char *)fname);    /* put the copy in its place */
  807.             if (stat((char *)fname, &st) >= 0)    /* original file does exist */
  808.                 remove((char *)backup);    /* throw away the copy */
  809. #else
  810.              rename((char *)backup, (char *)fname);    /* try to put the original file back */
  811. #endif
  812.         }
  813.          goto fail;
  814.      }
  815.     errmsg = NULL;
  816.  
  817.     if (end > buf->b_ml.ml_line_count)
  818.         end = buf->b_ml.ml_line_count;
  819.     len = 0;
  820.     s = buffer;
  821.     nchars = 0;
  822.     for (lnum = start; lnum <= end; ++lnum)
  823.     {
  824.         /*
  825.          * The next while loop is done once for each character written.
  826.          * Keep it fast!
  827.          */
  828.         ptr = ml_get_buf(buf, lnum, FALSE) - 1;
  829.         while ((c = *++ptr) != NUL)
  830.         {
  831.             if (c == NL)
  832.                 *s = NUL;        /* replace newlines with NULs */
  833.             else
  834.                 *s = c;
  835.             ++s;
  836.             if (++len != bufsize)
  837.                 continue;
  838.             if (write_buf(fd, buffer, bufsize) == FAIL)
  839.             {
  840.                 end = 0;                /* write error: break loop */
  841.                 break;
  842.             }
  843.             nchars += bufsize;
  844.             s = buffer;
  845.             len = 0;
  846.         }
  847.             /* write failed or last line has no EOL: stop here */
  848.         if (end == 0 || (buf->b_p_bin && lnum == buf->b_ml.ml_line_count && !buf->b_p_eol))
  849.             break;
  850.         if (buf->b_p_tx)        /* write CR-NL */
  851.         {
  852.             *s = CR;
  853.             ++s;
  854.             if (++len == bufsize)
  855.             {
  856.                 if (write_buf(fd, buffer, bufsize) == FAIL)
  857.                 {
  858.                     end = 0;                /* write error: break loop */
  859.                     break;
  860.                 }
  861.                 nchars += bufsize;
  862.                 s = buffer;
  863.                 len = 0;
  864.             }
  865.         }
  866.         *s = NL;
  867.         ++s;
  868.         if (++len == bufsize && end)
  869.         {
  870.             if (write_buf(fd, buffer, bufsize) == FAIL)
  871.             {
  872.                 end = 0;                /* write error: break loop */
  873.                 break;
  874.             }
  875.             nchars += bufsize;
  876.             s = buffer;
  877.             len = 0;
  878.         }
  879.     }
  880.     if (len && end)
  881.     {
  882.         if (write_buf(fd, buffer, len) == FAIL)
  883.             end = 0;                /* write error */
  884.         nchars += len;
  885.     }
  886.  
  887.     if (close(fd) != 0)
  888.     {
  889.         errmsg = (char_u *)"Close failed";
  890.         goto fail;
  891.     }
  892. #ifdef UNIX
  893.     if (made_writable)
  894.         perm &= ~0200;            /* reset 'w' bit for security reasons */
  895. #endif
  896.     if (perm >= 0)
  897.         (void)setperm(fname, perm);    /* set permissions of new file same as old file */
  898.  
  899.     if (end == 0)
  900.     {
  901.         errmsg = (char_u *)"write error (file system full?)";
  902.         goto fail;
  903.     }
  904.  
  905. #ifdef MSDOS        /* the screen may be messed up by the "insert disk
  906.                             in drive b: and hit return" message */
  907.     if (!exiting)
  908.         screenclear();
  909. #endif
  910.  
  911.     lnum -= start;            /* compute number of written lines */
  912.     --no_wait_return;        /* may wait for return now */
  913.  
  914.         /* careful: home_replace calls vimgetenv(), which also uses IObuff! */
  915.     home_replace(fname, IObuff + 1, IOSIZE - 1);
  916.     IObuff[0] = '"';
  917.     sprintf((char *)IObuff + STRLEN(IObuff),
  918.                     "\"%s%s %ld line%s, %ld character%s",
  919.             newfile ? " [New File]" : " ",
  920. #ifdef MSDOS
  921.             buf->b_p_tx ? "" : "[notextmode]",
  922. #else
  923.             buf->b_p_tx ? "[textmode]" : "",
  924. #endif
  925.             (long)lnum, plural((long)lnum),
  926.             nchars, plural(nchars));
  927.     msg(IObuff);
  928.  
  929.     if (reset_changed && whole)            /* when written everything */
  930.     {
  931.         UNCHANGED(buf);
  932.         u_unchanged(buf);
  933.         /*
  934.          * If written to the current file, update the timestamp of the swap file
  935.          * and reset the 'notedited' flag.
  936.          */
  937.         if (!exiting && buf->b_filename != NULL &&
  938.                             fnamecmp(ffname, buf->b_filename) == 0)
  939.         {
  940.             ml_timestamp(buf);
  941.             buf->b_notedited = FALSE;
  942.         }
  943.     }
  944.  
  945.     /*
  946.      * If we kept a backup until now, and we are in patch mode, then we make
  947.      * the backup file our 'original' file.
  948.      */
  949.     if (p_pm && *p_pm)
  950.     {
  951.         char *org = (char *)modname(fname, p_pm);
  952.  
  953.         if (backup != NULL)
  954.         {
  955.             struct stat st;
  956.  
  957.             /*
  958.              * If the original file does not exist yet
  959.              * the current backup file becomes the original file
  960.              */
  961.             if (org == NULL)
  962.                 EMSG("patchmode: can't save original file");
  963.             else if (stat(org, &st) < 0)
  964.             {
  965.                 rename((char *)backup, org);
  966.                 free(backup);            /* don't delete the file */
  967.                 backup = NULL;
  968.             }
  969.         }
  970.         /*
  971.          * If there is no backup file, remember that a (new) file was
  972.          * created.
  973.          */
  974.         else
  975.         {
  976.             int fd;
  977.  
  978.             if (org == NULL || (fd = open(org, O_CREAT, 0666)) < 0)
  979.               EMSG("patchmode: can't touch empty original file");
  980.             else
  981.               close(fd);
  982.         }
  983.         if (org != NULL)
  984.         {
  985.             setperm((char_u *)org, getperm(fname) & 0777);
  986.             free(org);
  987.         }
  988.     }
  989.  
  990.     /*
  991.      * Remove the backup unless 'backup' option is set
  992.      */
  993.     if (!p_bk && backup != NULL && remove((char *)backup) != 0)
  994.         EMSG("Can't delete backup file");
  995.     
  996.     goto nofail;
  997.  
  998. fail:
  999.     --no_wait_return;        /* may wait for return now */
  1000. #ifdef MSDOS                /* the screen may be messed up by the "insert disk
  1001.                                 in drive b: and hit return" message */
  1002.     screenclear();
  1003. #endif
  1004. nofail:
  1005.  
  1006.     free(backup);
  1007.     free(buffer);
  1008.  
  1009.     if (errmsg != NULL)
  1010.     {
  1011.         filemess(fname, errmsg);
  1012.         retval = FAIL;
  1013.     }
  1014.     return retval;
  1015. }
  1016.  
  1017. /*
  1018.  * write_buf: call write() to write a buffer
  1019.  *
  1020.  * return FAIL for failure, OK otherwise
  1021.  */
  1022.     static int
  1023. write_buf(fd, buf, len)
  1024.     int        fd;
  1025.     char_u    *buf;
  1026.     int        len;
  1027. {
  1028.     int        wlen;
  1029.  
  1030.     while (len)
  1031.     {
  1032.         wlen = write(fd, (char *)buf, (size_t)len);
  1033.         if (wlen <= 0)                /* error! */
  1034.             return FAIL;
  1035.         len -= wlen;
  1036.         buf += wlen;
  1037.     }
  1038.     return OK;
  1039. }
  1040.  
  1041. /*
  1042.  * do_mlines() - process mode lines for the current file
  1043.  *
  1044.  * Returns immediately if the "ml" parameter isn't set.
  1045.  */
  1046. static void     chk_mline __ARGS((linenr_t));
  1047.  
  1048.     static void
  1049. do_mlines()
  1050. {
  1051.     linenr_t        lnum;
  1052.     int             nmlines;
  1053.  
  1054.     if (!curbuf->b_p_ml || (nmlines = (int)p_mls) == 0)
  1055.         return;
  1056.  
  1057.     for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count && lnum <= nmlines; ++lnum)
  1058.         chk_mline(lnum);
  1059.  
  1060.     for (lnum = curbuf->b_ml.ml_line_count; lnum > 0 && lnum > nmlines &&
  1061.                             lnum > curbuf->b_ml.ml_line_count - nmlines; --lnum)
  1062.         chk_mline(lnum);
  1063. }
  1064.  
  1065. /*
  1066.  * chk_mline() - check a single line for a mode string
  1067.  */
  1068.     static void
  1069. chk_mline(lnum)
  1070.     linenr_t lnum;
  1071. {
  1072.     register char_u    *s;
  1073.     register char_u    *e;
  1074.     char_u            *cs;            /* local copy of any modeline found */
  1075.     int                prev;
  1076.     int                end;
  1077.  
  1078.     prev = ' ';
  1079.     for (s = ml_get(lnum); *s != NUL; ++s)
  1080.     {
  1081.         if (isspace(prev) && (STRNCMP(s, "vi:", (size_t)3) == 0 || STRNCMP(s, "ex:", (size_t)3) == 0 || STRNCMP(s, "vim:", (size_t)4) == 0))
  1082.         {
  1083.             do
  1084.                 ++s;
  1085.             while (s[-1] != ':');
  1086.             s = cs = strsave(s);
  1087.             if (cs == NULL)
  1088.                 break;
  1089.             end = FALSE;
  1090.             while (end == FALSE)
  1091.             {
  1092.                 while (*s == ' ' || *s == TAB)
  1093.                     ++s;
  1094.                 if (*s == NUL)
  1095.                     break;
  1096.                 for (e = s; (*e != ':' || *(e - 1) == '\\') && *e != NUL; ++e)
  1097.                     ;
  1098.                 if (*e == NUL)
  1099.                     end = TRUE;
  1100.                 *e = NUL;
  1101.                 if (STRNCMP(s, "set ", (size_t)4) == 0) /* "vi:set opt opt opt: foo" */
  1102.                 {
  1103.                     (void)doset(s + 4);
  1104.                     break;
  1105.                 }
  1106.                 if (doset(s) == FAIL)        /* stop if error found */
  1107.                     break;
  1108.                 s = e + 1;
  1109.             }
  1110.             free(cs);
  1111.             break;
  1112.         }
  1113.         prev = *s;
  1114.     }
  1115. }
  1116.  
  1117. /*
  1118.  * add extention to filename - change path/fo.o.h to path/fo.o.h.ext or
  1119.  * fo_o_h.ext for MSDOS or when dotfname option reset.
  1120.  *
  1121.  * Assumed that fname is a valid name found in the filesystem we assure that
  1122.  * the return value is a different name and ends in ".ext".
  1123.  * "ext" MUST start with a "." and MUST be at most 4 characters long.
  1124.  * Space for the returned name is allocated, must be freed later.
  1125.  */
  1126.  
  1127.     char_u *
  1128. modname(fname, ext)
  1129.     char_u *fname, *ext;
  1130. {
  1131.     return buf_modname(curbuf, fname, ext);
  1132. }
  1133.  
  1134.     char_u *
  1135. buf_modname(buf, fname, ext)
  1136.     BUF        *buf;
  1137.     char_u *fname, *ext;
  1138. {
  1139.     char_u            *retval;
  1140.     register char_u   *s;
  1141.     register char_u   *ptr;
  1142.     register int    fnamelen, extlen;
  1143.     char_u            currentdir[512];
  1144.  
  1145.     extlen = STRLEN(ext);
  1146.  
  1147.     /*
  1148.      * if there is no filename we must get the name of the current directory
  1149.      * (we need the full path in case :cd is used)
  1150.      */
  1151.     if (fname == NULL || *fname == NUL)
  1152.     {
  1153.         if (vim_dirname(currentdir, 510) == FAIL || (fnamelen = STRLEN(currentdir)) == 0)
  1154.             return NULL;
  1155.         if (!ispathsep(currentdir[fnamelen - 1]))
  1156.         {
  1157.             currentdir[fnamelen++] = PATHSEP;
  1158.             currentdir[fnamelen] = NUL;
  1159.         }
  1160.     }
  1161.     else
  1162.         fnamelen = STRLEN(fname);
  1163.     retval = alloc((unsigned) (fnamelen + extlen + 1));
  1164.     if (retval != NULL)
  1165.     {
  1166.         if (fname == NULL || *fname == NUL)
  1167.             STRCPY(retval, currentdir);
  1168.         else
  1169.             STRCPY(retval, fname);
  1170.         /*
  1171.          * search backwards until we hit a '/', '\' or ':' replacing all '.' by '_'
  1172.          * for MSDOS or when dotfname option reset.
  1173.          * Then truncate what is after the '/', '\' or ':' to 8 characters for MSDOS
  1174.          * and 26 characters for AMIGA and UNIX.
  1175.          */
  1176.         for (ptr = retval + fnamelen; ptr >= retval; ptr--)
  1177.         {
  1178. #ifndef MSDOS
  1179.             if (buf->b_p_sn || buf->b_shortname)
  1180. #endif
  1181.                 if (*ptr == '.')    /* replace '.' by '_' */
  1182.                     *ptr = '_';
  1183.             if (ispathsep(*ptr))
  1184.                 break;
  1185.         }
  1186.         ptr++;
  1187.  
  1188.         /* the filename has at most BASENAMELEN characters. */
  1189.         if (STRLEN(ptr) > (unsigned)BASENAMELEN)
  1190.             ptr[BASENAMELEN] = '\0';
  1191. #ifndef MSDOS
  1192.         if ((buf->b_p_sn || buf->b_shortname) && STRLEN(ptr) > (unsigned)8)
  1193.             ptr[8] = '\0';
  1194. #endif
  1195.         s = ptr + STRLEN(ptr);
  1196.  
  1197.         /*
  1198.          * Append the extention.
  1199.          * ext must start with '.' and cannot exceed 3 more characters.
  1200.          */
  1201.         STRCPY(s, ext);
  1202. #ifdef MSDOS
  1203.         if (fname == NULL || *fname == NUL)        /* can't have just the extension */
  1204.             *s = '_';
  1205. #endif
  1206.         if (fname != NULL && STRCMP(fname, retval) == 0)
  1207.         {
  1208.             /* after modification still the same name? */
  1209.             /* we search for a character that can be replaced by '_' */
  1210.             while (--s >= ptr)
  1211.             {
  1212.                 if (*s != '_')
  1213.                 {
  1214.                     *s = '_';
  1215.                     break;
  1216.                 }
  1217.             }
  1218.             if (s < ptr)
  1219.             {
  1220.                 /* fname was "________.<ext>" how tricky! */
  1221.                 *ptr = 'v';
  1222.             }
  1223.         }
  1224.     }
  1225.     return retval;
  1226. }
  1227.  
  1228. #ifdef WEBB_COMPLETE
  1229. /* vim_fgets();
  1230.  *
  1231.  * Like fgets(), but if the file line is too long, it is truncated and the
  1232.  * rest of the line is thrown away.  Returns TRUE or FALSE for end-of-file or
  1233.  * not.  The integer pointed to by lnum is incremented.  Note: do not pass
  1234.  * IObuff as the buffer since this is used to read and discard the extra part
  1235.  * of any long lines.
  1236.  */
  1237.     int
  1238. vim_fgets(buf, size, fp, lnum)
  1239.     char_u *buf;
  1240.     int size;
  1241.     FILE *fp;
  1242.     int *lnum;
  1243. {
  1244.     char *eof;
  1245.  
  1246.     buf[size - 2] = NUL;
  1247.     eof = fgets((char *)buf, size, fp);
  1248.     if (buf[size - 2] != NUL && buf[size - 2] != '\n')
  1249.     {
  1250.         buf[size - 1] = NUL;        /* Truncate the line */
  1251.  
  1252.         /* Now throw away the rest of the line: */
  1253.         do
  1254.         {
  1255.             IObuff[IOSIZE - 2] = NUL;
  1256.             eof = fgets((char *)IObuff, IOSIZE, fp);
  1257.         } while (IObuff[IOSIZE - 2] != NUL && IObuff[IOSIZE - 2] != '\n');
  1258.         return FALSE;
  1259.     }
  1260.     ++*lnum;
  1261.     return (eof == NULL);
  1262. }
  1263. #endif /* WEBB_COMPLETE */
  1264.